<?php
/**
 * QQAS - share your knowledge to the world!
 *
 * @author		xiaochong0302 <xiaochong0302@gmail.com>
 * @copyright	Copyright (c) 2011, Koogua Studio.
 * @license		http://www.qqas.org/user_guide/license.html
 * @link		http://www.qqas.org
 * @since		Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * Database
 *
 * @category	Admin
 */
class DatabaseAction extends AdminAction
{

    protected $backupPath;

	public function _initialize()
	{
	   parent::_initialize();
	    $this->backupPath = DATA_PATH . '_sqlBackups/';
	}


    /**
     * 数据导出
     *
     */
	public function dbExport()
	{
		$Model = M();
		$path = $this->backupPath;
		$runLog = $path .'run.log';

		if (!is_writable($path))
		{
		    $errorMsg = sprintf(L('path_not_writable'), $path);
		    $this->error($errorMsg);
		}

		$allTables = $Model->query(" SHOW TABLES ");
		foreach ($allTables as $table)
		{
			foreach ($table as $value)
			{
				$tables[] = $value;
			}
		}

		if (isset($_REQUEST['op']) && 'save' == $_REQUEST['op'])
		{
			import('@.Util.SqlDump');
			@set_time_limit(300);
			$SqlDump = new SqlDump($Model);

			$maxSize = intval($_REQUEST['vol_size']);
			$sqlFileName = empty($_REQUEST['sql_file_name']) ? date('YmdHis') : $_REQUEST['sql_file_name'];
			$fileType = empty($_REQUEST['file_type']) ? '.sql' : $_REQUEST['file_type'];
		    $vol = empty($_REQUEST['vol']) ? 1 : intval($_REQUEST['vol']);
		    $SqlDump->is_short = TRUE;

		    /*-------------- 单卷长度不超过5M -------------*/
		    if ($maxSize > 5 * 1024 || $maxSize <= 0)
		    {
		        $maxSize = 5 * 1024;
		    }
		    $SqlDump->max_size = $maxSize * 1024;

		    /*-------------- 获取要备份数据列表 -------------*/
			if ('all' == $_POST['target_table'])  //全部备份
			{
				foreach ($tables as $table)
				{
					$tables[$table] = -1;
				}
				$SqlDump->put_tables_list($runLog, $tables);
			}
			else if('custom' == $_POST['target_table'])  //自定义备份
			{
				$tables = $_POST['tables'];
				if (empty($tables))
				{
					$this->error(L('db.no_table_selected'));
				}
				else
				{
					foreach ($tables as $table)
					{
		                $tables[$table] = -1;
		            }
		            $SqlDump->put_tables_list($runLog, $tables);
				}
			}

			/*------------------------ 开始备份 -------------------------*/
			$tables = $SqlDump->dump_table($runLog, $vol);
		    if ($tables === false)
		    {
		        $this->error($SqlDump->error_msg());
		    }
		    if (empty($tables)) //备份结束
		    {
		        if ($vol > 1) //多分卷
		        {
					$filename = $path . $sqlFileName . '_vol' . $vol . '.sql';
					for ($i=1; $i<=$vol; $i++)
					{
					    $files[] = $path . $sqlFileName . '_vol' . $i . '.sql';
					}
				}
				else //只有一个文件
				{
					$filename = $path . $sqlFileName . '.sql';
					$files[] = $filename;
				}
		    	if (!@file_put_contents($filename, $SqlDump->dump_sql))
		    	{
		    	    $errorMsg = sprintf(L('path_not_writable'), $filename);
			        $this->error($errorMsg);
	            }

	            /*-------------------- 创建压缩文档 --------------------*/
	            if (!empty($fileType) && '.sql' != $fileType)
	            {
	                vendor('PclZip.pclzip');
	                $archive = new PclZip($this->backupPath.$sqlFileName.$fileType);
                    if ($archive->create($files, PCLZIP_OPT_REMOVE_ALL_PATH) == 0)
                    {
                        die('Error : '.$archive->errorInfo(true));
                    }
                    //清理原始文件
                    $handle = opendir($this->backupPath);
    	            while ($file = readdir($handle))
    	            {
    	                if (preg_match('/^'.$sqlFileName.'.*?\.sql$/', $file) && is_file($this->backupPath .$file))
    	                {
    	                    @unlink($this->backupPath .$file);
    	                }
    	            }
	            }
	            $this->assign('jumpUrl', __URL__.'/dbExport');
				$this->success(L('db.backup_complete'));
		    }
		    else //下一个页面处理
		    {
		    	$filename = $path . $sqlFileName . '_vol' . $vol . '.sql';
		        if (!@file_put_contents($filename, $SqlDump->dump_sql))
		        {
	                $errorMsg = sprintf(L('path_not_writable'), $filename);
			        $this->error($errorMsg);
	            }
		        $link  = __URL__ .'/dbExport/?op=save&sql_file_name='.$sqlFileName;
		        $link .= '&vol_size='.$maxSize.'&file_type='.$fileType.'&vol='.($vol+1);

		        $message = sprintf(L('db.vol_created_succeed'), $vol);
		        $this->assign('jumpUrl', $link);
		        $this->success($message);
		    }
		}
		else
		{
    		$this->assign('tables', $tables);
			$this->assign('volSize', 2048);
			$this->display();
		}
	}


	/**
	 * 数据恢复
	 *
	 */
	public function dbImport()
	{
	    import('@.Util.SqlDump');

	    $Model = M();
	    $SqlDump = new SqlDump($Model);

		if (isset($_REQUEST['op']) && 'save' == $_REQUEST['op'])
		{
		    if (!C('ACP_RESTORE_DB_ENABLE'))
	        {
	    	    $this->error(L('db.restore_db_disabled'));
	        }

		    @set_time_limit(300);
		    $fileName = empty($_REQUEST['file_name']) ? '' : trim($_REQUEST['file_name']);
		    $fileList = array();

		    if (preg_match('/\.(zip|gz|bz2)$/', $fileName))
		    {
		        vendor('PclZip.pclzip');
		    	$archive = new PclZip($this->backupPath.$fileName);
                if ($archive->extract(PCLZIP_OPT_PATH, $this->backupPath) == 0)
                {
                    die('Error : '.$archive->errorInfo(true));
                }
                $compress = TRUE;
		    }

		    $name = substr($fileName, 0, strrpos($fileName, '.'));

	        $handle = opendir($this->backupPath);
	        while ($file = readdir($handle))
	        {
                if ('.' != $file && '..' != $file && preg_match('/^'.$name.'.*?\.sql$/', $file))
                {
                    $fileList[] = $this->backupPath .$file;
                }
	        }
	        natsort($fileList);

		    /*------------------ 开始恢复数据 ------------------*/
		    if (!empty($fileList))
		    {
		        foreach ($fileList as $file)
		        {
		            if (!file_exists($file))
		            {
		                $errorMsg = sprintf(L('path_not_exist'), $file);
		            	$this->error($errorMsg);
		            }
		            $info = $SqlDump->get_head($file);
		            if ($info['software_version'] != get_site_config('software_version'))
		            {
		                $this->error(L('db.backup_version_not_equal'));
		            }
		            if (!$SqlDump->sql_import($file))
		            {
		                $this->error(L('db.backup_restored_failed'));
		            }
		            //清理解压后的文件
		            if ($compress)
		            {
		                @unlink($file);
		            }
		        }
		    }
            $this->success(L('db.backup_restored_succeed'));
		}
		else
		{
			/*---------------- 获取备份文件列表 ------------------*/
	        $handle = opendir($this->backupPath);
	        while ($file = readdir($handle))
	        {
	            if('.' != $file && '..' != $file && 'run.log' != $file)
	            {
    	            if (preg_match('/_vol[0-9]+/', $file))
    	            {
    	                $name = substr($file, 0, strrpos($file, '_'));
    	                $ext = substr($file, strrpos($file, '.'));
    	                $fileList[$name]['name'] = $name.$ext;
    	                $fileList[$name]['time'] = filemtime($this->backupPath.$file);
    	                $fileList[$name]['size'] += filesize($this->backupPath.$file);
    	            }
    	            else
    	            {
    	                $name = $file;
    	                $fileList[$name]['name'] = $file;
    	                $fileList[$name]['time'] = filemtime($this->backupPath.$file);
    	                $fileList[$name]['size'] = filesize($this->backupPath.$file);
    	            }
	            }
	        }
			$this->assign('fileList', $fileList);
			$this->display();
		}
	}


    /**
     * 删除数据备份
     *
     */
	public function removeBackup()
	{
		if (empty($_POST['backups']))
		{
			$this->redirect('Admin-Database/dbImport');
		}

		if ($this->isPost())
		{
            $handle = opendir($this->backupPath);
            while ($file = readdir($handle))
            {
                foreach ($_POST['backups'] as $value)
                {
                    $name = substr($value, 0, strrpos($value, '.'));
                    if ('.' != $file && '..' != $file && false !== strpos($file, $name))
                    {
                        @unlink($this->backupPath.$file);
                    }
                }
            }
            $this->assign('jumpUrl', __URL__.'/dbImport');
	        $this->success(L('db.backup_deleted_succeed'));
	    }
	}


	/**
	 * 下载备份
	 *
	 */
	function downloadBackup()
	{
	    import('ORG.Net.Http');

	    $fileName = $_GET['file_name'];
	    $name = substr($fileName, 0, strrpos($fileName, '.'));
	    $handle = opendir($this->backupPath);
	    //多分卷文件自动合并
        while ($file = readdir($handle))
        {
            if ('.' != $file && '..' != $file && false !== strpos($file, $name))
            {
                $content .= file_get_contents($this->backupPath.$file);
            }
        }
        if (strlen($content) > 0)
        {
            Http::download($fileName, '', $content);
        }
	}


	/**
	 * 优化数据表
	 *
	 */
	public function dbOptimize()
	{
		$Model = M();
		$this->assign('jumpUrl', __ACTION__);
		if ($this->isPost())
		{
			if (empty($_POST['tables']))
			{
			 	$this->error(L('db.no_table_selected'));
			}
			else
			{
				$tables = implode(',', $_POST['tables']);
				$Model->query(" OPTIMIZE TABLE {$tables} ");
				$this->success(L('db.table_optimized_succeed'));
			}
		}
		else
		{
			$dataLength = $indexLength = $dbRows = $dbSize = $dataFree = 0;
			$results = $tables = array();
		    $results = $Model->query("SHOW TABLE STATUS");
		    foreach ($results as $row)
		    {
		    	$dbRows += $row['Rows'];
		        $dataLength += $row['Data_length'];
		        $indexLength += $row['Index_length'];
		        $dataFree += $row['Data_free'];
		        $row['Data_length'] = byte_format($row['Data_length']);
		        $row['Index_length'] = byte_format($row['Index_length']);
		        $row['Data_free'] = byte_format($row['Data_free']);
		        $tables[] = $row;
		    }
		    $this->assign('indexSize', byte_format($indexLength));
		    $this->assign('dataSize', byte_format($dataLength));
		    $this->assign('dataFreeSize', byte_format($dataFree));
		    $this->assign('dbSize', byte_format($dataLength + $indexLength));
		    $this->assign('dbRows', $dbRows);
		    $this->assign('tableList', $tables);
		    $this->display();
		}
	}



}
// End  Class

/* End of file DatabaseAction.class.php */
/* Location: /var/www/qqas/App/Lib/Action/Admin/DatabaseAction.class.php */